#include "string_utils.h"

#define NULL ((void *)0)

/*
 * NOTE! This ctype does not handle EOF like the standard C
 * library is required to.
 */

#define _U 0x01  /* upper */
#define _L 0x02  /* lower */
#define _D 0x04  /* digit */
#define _C 0x08  /* cntrl */
#define _P 0x10  /* punct */
#define _S 0x20  /* white space (space/lf/tab) */
#define _X 0x40  /* hex digit */
#define _SP 0x80 /* hard space (0x20) */

//==============================
unsigned char _ctype[] = {_C,       _C,      _C,      _C,      _C,      _C,
                          _C,       _C, /* 0-7 */
                          _C,       _C | _S, _C | _S, _C | _S, _C | _S, _C | _S,
                          _C,       _C, /* 8-15 */
                          _C,       _C,      _C,      _C,      _C,      _C,
                          _C,       _C, /* 16-23 */
                          _C,       _C,      _C,      _C,      _C,      _C,
                          _C,       _C, /* 24-31 */
                          _S | _SP, _P,      _P,      _P,      _P,      _P,
                          _P,       _P, /* 32-39 */
                          _P,       _P,      _P,      _P,      _P,      _P,
                          _P,       _P, /* 40-47 */
                          _D,       _D,      _D,      _D,      _D,      _D,
                          _D,       _D, /* 48-55 */
                          _D,       _D,      _P,      _P,      _P,      _P,
                          _P,       _P, /* 56-63 */
                          _P,       _U | _X, _U | _X, _U | _X, _U | _X, _U | _X,
                          _U | _X,  _U, /* 64-71 */
                          _U,       _U,      _U,      _U,      _U,      _U,
                          _U,       _U, /* 72-79 */
                          _U,       _U,      _U,      _U,      _U,      _U,
                          _U,       _U, /* 80-87 */
                          _U,       _U,      _U,      _P,      _P,      _P,
                          _P,       _P, /* 88-95 */
                          _P,       _L | _X, _L | _X, _L | _X, _L | _X, _L | _X,
                          _L | _X,  _L, /* 96-103 */
                          _L,       _L,      _L,      _L,      _L,      _L,
                          _L,       _L, /* 104-111 */
                          _L,       _L,      _L,      _L,      _L,      _L,
                          _L,       _L, /* 112-119 */
                          _L,       _L,      _L,      _P,      _P,      _P,
                          _P,       _C, /* 120-127 */
                          0,        0,       0,       0,       0,       0,
                          0,        0,       0,       0,       0,       0,
                          0,        0,       0,       0, /* 128-143 */
                          0,        0,       0,       0,       0,       0,
                          0,        0,       0,       0,       0,       0,
                          0,        0,       0,       0, /* 144-159 */
                          _S | _SP, _P,      _P,      _P,      _P,      _P,
                          _P,       _P,      _P,      _P,      _P,      _P,
                          _P,       _P,      _P,      _P, /* 160-175 */
                          _P,       _P,      _P,      _P,      _P,      _P,
                          _P,       _P,      _P,      _P,      _P,      _P,
                          _P,       _P,      _P,      _P, /* 176-191 */
                          _U,       _U,      _U,      _U,      _U,      _U,
                          _U,       _U,      _U,      _U,      _U,      _U,
                          _U,       _U,      _U,      _U, /* 192-207 */
                          _U,       _U,      _U,      _U,      _U,      _U,
                          _U,       _P,      _U,      _U,      _U,      _U,
                          _U,       _U,      _U,      _L, /* 208-223 */
                          _L,       _L,      _L,      _L,      _L,      _L,
                          _L,       _L,      _L,      _L,      _L,      _L,
                          _L,       _L,      _L,      _L, /* 224-239 */
                          _L,       _L,      _L,      _L,      _L,      _L,
                          _L,       _P,      _L,      _L,      _L,      _L,
                          _L,       _L,      _L,      _L};

#define __ismask(x) (_ctype[(int)(unsigned char)(x)])

#define isalnum(c) ((__ismask(c) & (_U | _L | _D)) != 0)
#define isalpha(c) ((__ismask(c) & (_U | _L)) != 0)
#define iscntrl(c) ((__ismask(c) & (_C)) != 0)
#define isdigit(c) ((__ismask(c) & (_D)) != 0)
#define isgraph(c) ((__ismask(c) & (_P | _U | _L | _D)) != 0)
#define islower(c) ((__ismask(c) & (_L)) != 0)
#define isprint(c) ((__ismask(c) & (_P | _U | _L | _D | _SP)) != 0)
#define ispunct(c) ((__ismask(c) & (_P)) != 0)
#define isspace(c) ((__ismask(c) & (_S)) != 0)
#define isupper(c) ((__ismask(c) & (_U)) != 0)
#define isxdigit(c) ((__ismask(c) & (_D | _X)) != 0)

/*
 * Rather than doubling the size of the _ctype lookup table to hold a 'blank'
 * flag, just check for space or tab.
 */
#define isblank(c) (c == ' ' || c == '\t')

#define isascii(c) (((unsigned char)(c)) <= 0x7f)
#define toascii(c) (((unsigned char)(c)) & 0x7f)

static inline unsigned char __tolower(unsigned char c) {
    if (isupper(c)) c -= 'A' - 'a';
    return c;
}

static inline unsigned char __toupper(unsigned char c) {
    if (islower(c)) c -= 'a' - 'A';
    return c;
}

#define tolower(c) __tolower(c)
#define toupper(c) __toupper(c)

unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) {
    unsigned long result = 0, value;

    if (*cp == '0') {
        cp++;
        if ((*cp == 'x' || *cp == 'X') && isxdigit(cp[1])) {
            base = 16;
            cp++;
        }
        if (!base) {
            base = 8;
        }
    }
    if (!base) {
        base = 10;
    }
    while (isxdigit(*cp) &&
           (value = isdigit(*cp) ? *cp - '0'
                                 : (islower(*cp) ? toupper(*cp) : *cp) - 'A' +
                                       10) < base) {
        result = result * base + value;
        cp++;
    }
    if (endp) *endp = (char *)cp;
    return result;
}

long simple_strtol(const char *cp, char **endp, unsigned int base) {
    if (*cp == '-') return -simple_strtoul(cp + 1, endp, base);
    return simple_strtoul(cp, endp, base);
}

char *gets(char s[]) {
    int i = 0;
    char c;

    while (1) {
        c = getchar();

        putchar(c);
        if (c == '\n')
            putchar('\r');
        else if (c == '\r')
            putchar('\n');

        if ((c == '\n') || (c == '\r')) {
            s[i] = '\0';
            break;
        } else {
            s[i++] = c;
        }
    }

    return s;
}

/**
 * strlen - Find the length of a string
 * @s: The string to be sized
 */
int strlen(const char *s) {
    const char *sc;

    for (sc = s; *sc != '\0'; ++sc) /* nothing */;
    return sc - s;
}

/**
 * strcmp - Compare two strings
 * @cs: One string
 * @ct: Another string
 */
int strcmp(const char *cs, const char *ct) {
    register signed char __res;

    while (1) {
        if ((__res = *cs - *ct++) != 0 || !*cs++) break;
    }

    return __res;
}

int get_int(void) {
    char str[100];
    gets(str);
    return simple_strtol(str, NULL, 0);
}

unsigned int get_uint(void) {
    char str[100];
    gets(str);
    return simple_strtoul(str, NULL, 0);
}
